# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.1179+1.1069.1.254 -> 1.1180 # include/linux/sysctl.h 1.23.1.21 -> 1.44 # drivers/char/agp/agpgart_be.c 1.35.1.20 -> 1.63 # drivers/net/tg3.c 1.61.2.66 -> 1.82 # diff -Nru a/drivers/char/agp/agpgart_be.c b/drivers/char/agp/agpgart_be.c --- a/drivers/char/agp/agpgart_be.c Fri Mar 12 15:59:51 2004 +++ b/drivers/char/agp/agpgart_be.c Fri Mar 12 15:59:51 2004 @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -217,10 +218,14 @@ agp_bridge.free_by_type(curr); return; } - if (curr->page_count != 0) { - for (i = 0; i < curr->page_count; i++) { - agp_bridge.agp_destroy_page((unsigned long) - phys_to_virt(curr->memory[i])); + if (agp_bridge.cant_use_aperture) { + vfree(curr->vmptr); + } else { + if (curr->page_count != 0) { + for (i = 0; i < curr->page_count; i++) { + agp_bridge.agp_destroy_page((unsigned long) + phys_to_virt(curr->memory[i])); + } } } agp_free_key(curr->key); @@ -229,6 +234,8 @@ MOD_DEC_USE_COUNT; } +#define IN_VMALLOC(_x) (((_x) >= VMALLOC_START) && ((_x) < VMALLOC_END)) + #define ENTRIES_PER_PAGE (PAGE_SIZE / sizeof(unsigned long)) agp_memory *agp_allocate_memory(size_t page_count, u32 type) @@ -263,18 +270,43 @@ MOD_DEC_USE_COUNT; return NULL; } - for (i = 0; i < page_count; i++) { - new->memory[i] = agp_bridge.agp_alloc_page(); - if (new->memory[i] == 0) { - /* Free this structure */ - agp_free_memory(new); + if (agp_bridge.cant_use_aperture) { + void *vmblock; + unsigned long vaddr; + struct page *page; + + vmblock = __vmalloc(page_count << PAGE_SHIFT, GFP_KERNEL, PAGE_KERNEL); + if (vmblock == NULL) { + MOD_DEC_USE_COUNT; return NULL; } - new->memory[i] = virt_to_phys((void *) new->memory[i]); - new->page_count++; - } + new->vmptr = vmblock; + vaddr = (unsigned long) vmblock; + + for (i = 0; i < page_count; i++, vaddr += PAGE_SIZE) { + page = vmalloc_to_page((void *) vaddr); + if (!page) { + MOD_DEC_USE_COUNT; + return NULL; + } + new->memory[i] = virt_to_phys(page_address(page)); + } + + new->page_count = page_count; + } else { + for (i = 0; i < page_count; i++) { + new->memory[i] = agp_bridge.agp_alloc_page(); + if (new->memory[i] == 0) { + /* Free this structure */ + agp_free_memory(new); + return NULL; + } + new->memory[i] = virt_to_phys((void *) new->memory[i]); + new->page_count++; + } + } return new; } @@ -287,26 +319,18 @@ temp = agp_bridge.current_size; - switch (agp_bridge.size_type) { - case U8_APER_SIZE: + if (agp_bridge.size_type == U8_APER_SIZE) current_size = A_SIZE_8(temp)->size; - break; - case U16_APER_SIZE: + else if (agp_bridge.size_type == U16_APER_SIZE) current_size = A_SIZE_16(temp)->size; - break; - case U32_APER_SIZE: + else if (agp_bridge.size_type == U32_APER_SIZE) current_size = A_SIZE_32(temp)->size; - break; - case LVL2_APER_SIZE: + else if (agp_bridge.size_type == LVL2_APER_SIZE) current_size = A_SIZE_LVL2(temp)->size; - break; - case FIXED_APER_SIZE: + else if (agp_bridge.size_type == FIXED_APER_SIZE) current_size = A_SIZE_FIX(temp)->size; - break; - default: + else current_size = 0; - break; - } current_size -= (agp_memory_reserved / (1024*1024)); @@ -315,6 +339,9 @@ /* Routine to copy over information structure */ +/* AGP bridge need not be PCI device, but DRM thinks it is. */ +static struct pci_dev fake_bridge_dev; + int agp_copy_info(agp_kern_info * info) { memset(info, 0, sizeof(agp_kern_info)); @@ -324,7 +351,7 @@ } info->version.major = agp_bridge.version->major; info->version.minor = agp_bridge.version->minor; - info->device = agp_bridge.dev; + info->device = agp_bridge.dev ? agp_bridge.dev : &fake_bridge_dev; info->chipset = agp_bridge.type; info->mode = agp_bridge.mode; info->aper_base = agp_bridge.gart_bus_addr; @@ -398,97 +425,104 @@ /* Generic Agp routines - Start */ -static void agp_generic_agp_enable(u32 mode) +static u32 agp_collect_device_status(u32 mode, u32 command) { - struct pci_dev *device = NULL; - u32 command, scratch; - u8 cap_ptr; + struct pci_dev *device; + u8 agp; + u32 scratch; - pci_read_config_dword(agp_bridge.dev, - agp_bridge.capndx + 4, - &command); + pci_for_each_dev(device) { + agp = pci_find_capability(device, PCI_CAP_ID_AGP); + if (!agp) + continue; - /* - * PASS1: go throu all devices that claim to be - * AGP devices and collect their data. - */ + /* + * Ok, here we have a AGP device. Disable impossible + * settings, and adjust the readqueue to the minimum. + */ + pci_read_config_dword(device, agp + PCI_AGP_STATUS, &scratch); + /* adjust RQ depth */ + command = + ((command & ~0xff000000) | + min_t(u32, (mode & 0xff000000), + min_t(u32, (command & 0xff000000), + (scratch & 0xff000000)))); + + /* disable SBA if it's not supported */ + if (!((command & 0x00000200) && + (scratch & 0x00000200) && + (mode & 0x00000200))) + command &= ~0x00000200; + + /* disable FW if it's not supported */ + if (!((command & 0x00000010) && + (scratch & 0x00000010) && + (mode & 0x00000010))) + command &= ~0x00000010; - pci_for_each_dev(device) { - cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP); - if (cap_ptr != 0x00) { - /* - * Ok, here we have a AGP device. Disable impossible - * settings, and adjust the readqueue to the minimum. - */ - - pci_read_config_dword(device, cap_ptr + 4, &scratch); - - /* adjust RQ depth */ - command = - ((command & ~0xff000000) | - min_t(u32, (mode & 0xff000000), - min_t(u32, (command & 0xff000000), - (scratch & 0xff000000)))); - - /* disable SBA if it's not supported */ - if (!((command & 0x00000200) && - (scratch & 0x00000200) && - (mode & 0x00000200))) - command &= ~0x00000200; - - /* disable FW if it's not supported */ - if (!((command & 0x00000010) && - (scratch & 0x00000010) && - (mode & 0x00000010))) - command &= ~0x00000010; - - if (!((command & 4) && - (scratch & 4) && - (mode & 4))) - command &= ~0x00000004; - - if (!((command & 2) && - (scratch & 2) && - (mode & 2))) - command &= ~0x00000002; - - if (!((command & 1) && - (scratch & 1) && - (mode & 1))) - command &= ~0x00000001; - } + if (!((command & 4) && + (scratch & 4) && + (mode & 4))) + command &= ~0x00000004; + + if (!((command & 2) && + (scratch & 2) && + (mode & 2))) + command &= ~0x00000002; + + if (!((command & 1) && + (scratch & 1) && + (mode & 1))) + command &= ~0x00000001; } - /* - * PASS2: Figure out the 4X/2X/1X setting and enable the - * target (our motherboard chipset). - */ - if (command & 4) { + if (command & 4) command &= ~3; /* 4X */ + if (command & 2) + command &= ~5; /* 2X (8X for AGP3.0) */ + if (command & 1) + command &= ~6; /* 1X (4X for AGP3.0) */ + + return command; +} + +static void agp_device_command(u32 command, int agp_v3) +{ + struct pci_dev *device; + int mode; + + mode = command & 0x7; + if (agp_v3) + mode *= 4; + + pci_for_each_dev(device) { + u8 agp = pci_find_capability(device, PCI_CAP_ID_AGP); + if (!agp) + continue; + + printk(KERN_INFO PFX "Putting AGP V%d device at %s into %dx mode\n", + agp_v3 ? 3 : 2, device->slot_name, mode); + pci_write_config_dword(device, agp + PCI_AGP_COMMAND, command); } - if (command & 2) { - command &= ~5; /* 2X */ - } - if (command & 1) { - command &= ~6; /* 1X */ - } +} + +static void agp_generic_agp_enable(u32 mode) +{ + u32 command; + + pci_read_config_dword(agp_bridge.dev, + agp_bridge.capndx + PCI_AGP_STATUS, + &command); + + command = agp_collect_device_status(mode, command); command |= 0x00000100; pci_write_config_dword(agp_bridge.dev, - agp_bridge.capndx + 8, + agp_bridge.capndx + PCI_AGP_COMMAND, command); - /* - * PASS3: Go throu all AGP devices and update the - * command registers. - */ - - pci_for_each_dev(device) { - cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP); - if (cap_ptr != 0x00) - pci_write_config_dword(device, cap_ptr + 8, command); - } + agp_device_command(command, 0); } static int agp_generic_create_gatt_table(void) @@ -3641,7 +3675,6 @@ struct pci_dev *device = NULL; u32 command, scratch; u8 cap_ptr; - u8 agp_v3; u8 v3_devs=0; /* FIXME: If 'mode' is x1/x2/x4 should we call the AGPv2 routines directly ? @@ -3674,77 +3707,14 @@ } - pci_read_config_dword(agp_bridge.dev, agp_bridge.capndx + 4, &command); - - /* - * PASS2: go through all devices that claim to be - * AGP devices and collect their data. - */ - - pci_for_each_dev(device) { - cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP); - if (cap_ptr != 0x00) { - /* - * Ok, here we have a AGP device. Disable impossible - * settings, and adjust the readqueue to the minimum. - */ - - printk (KERN_INFO "AGP: Setting up AGPv3 capable device at %d:%d:%d\n", - device->bus->number, PCI_FUNC(device->devfn), PCI_SLOT(device->devfn)); - pci_read_config_dword(device, cap_ptr + 4, &scratch); - agp_v3 = (scratch & (1<<3) ) >>3; - - /* adjust RQ depth */ - command = - ((command & ~0xff000000) | - min_t(u32, (mode & 0xff000000), - min_t(u32, (command & 0xff000000), - (scratch & 0xff000000)))); - - /* disable SBA if it's not supported */ - if (!((command & 0x200) && (scratch & 0x200) && (mode & 0x200))) - command &= ~0x200; - - /* disable FW if it's not supported */ - if (!((command & 0x10) && (scratch & 0x10) && (mode & 0x10))) - command &= ~0x10; - - if (!((command & 2) && (scratch & 2) && (mode & 2))) { - command &= ~2; /* 8x */ - printk (KERN_INFO "AGP: Putting device into 8x mode\n"); - } - - if (!((command & 1) && (scratch & 1) && (mode & 1))) { - command &= ~1; /* 4x */ - printk (KERN_INFO "AGP: Putting device into 4x mode\n"); - } - } - } - /* - * PASS3: Figure out the 8X/4X setting and enable the - * target (our motherboard chipset). - */ - - if (command & 2) - command &= ~5; /* 8X */ - - if (command & 1) - command &= ~6; /* 4X */ + pci_read_config_dword(agp_bridge.dev, agp_bridge.capndx + PCI_AGP_STATUS, &command); + command = agp_collect_device_status(mode, command); command |= 0x100; - pci_write_config_dword(agp_bridge.dev, agp_bridge.capndx + 8, command); - - /* - * PASS4: Go through all AGP devices and update the - * command registers. - */ + pci_write_config_dword(agp_bridge.dev, agp_bridge.capndx + PCI_AGP_COMMAND, command); - pci_for_each_dev(device) { - cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP); - if (cap_ptr != 0x00) - pci_write_config_dword(device, cap_ptr + 8, command); - } + agp_device_command(command, 1); } @@ -4457,7 +4427,7 @@ /* Fill in the mode register */ pci_read_config_dword(serverworks_private.svrwrks_dev, - agp_bridge.capndx + 4, + agp_bridge.capndx + PCI_AGP_STATUS, &agp_bridge.mode); pci_read_config_byte(agp_bridge.dev, @@ -4607,104 +4577,23 @@ static void serverworks_agp_enable(u32 mode) { - struct pci_dev *device = NULL; - u32 command, scratch, cap_id; - u8 cap_ptr; + u32 command; pci_read_config_dword(serverworks_private.svrwrks_dev, - agp_bridge.capndx + 4, + agp_bridge.capndx + PCI_AGP_STATUS, &command); - /* - * PASS1: go throu all devices that claim to be - * AGP devices and collect their data. - */ - - - pci_for_each_dev(device) { - cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP); - if (cap_ptr != 0x00) { - do { - pci_read_config_dword(device, - cap_ptr, &cap_id); - - if ((cap_id & 0xff) != 0x02) - cap_ptr = (cap_id >> 8) & 0xff; - } - while (((cap_id & 0xff) != 0x02) && (cap_ptr != 0x00)); - } - if (cap_ptr != 0x00) { - /* - * Ok, here we have a AGP device. Disable impossible - * settings, and adjust the readqueue to the minimum. - */ - - pci_read_config_dword(device, cap_ptr + 4, &scratch); - - /* adjust RQ depth */ - command = - ((command & ~0xff000000) | - min_t(u32, (mode & 0xff000000), - min_t(u32, (command & 0xff000000), - (scratch & 0xff000000)))); - - /* disable SBA if it's not supported */ - if (!((command & 0x00000200) && - (scratch & 0x00000200) && - (mode & 0x00000200))) - command &= ~0x00000200; - - /* disable FW */ - command &= ~0x00000010; - - command &= ~0x00000008; - - if (!((command & 4) && - (scratch & 4) && - (mode & 4))) - command &= ~0x00000004; - - if (!((command & 2) && - (scratch & 2) && - (mode & 2))) - command &= ~0x00000002; - - if (!((command & 1) && - (scratch & 1) && - (mode & 1))) - command &= ~0x00000001; - } - } - /* - * PASS2: Figure out the 4X/2X/1X setting and enable the - * target (our motherboard chipset). - */ + command = agp_collect_device_status(mode, command); - if (command & 4) { - command &= ~3; /* 4X */ - } - if (command & 2) { - command &= ~5; /* 2X */ - } - if (command & 1) { - command &= ~6; /* 1X */ - } + command &= ~0x00000010; /* disable FW */ + command &= ~0x00000008; command |= 0x00000100; pci_write_config_dword(serverworks_private.svrwrks_dev, - agp_bridge.capndx + 8, + agp_bridge.capndx + PCI_AGP_COMMAND, command); - /* - * PASS3: Go throu all AGP devices and update the - * command registers. - */ - - pci_for_each_dev(device) { - cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP); - if (cap_ptr != 0x00) - pci_write_config_dword(device, cap_ptr + 8, command); - } + agp_device_command(command, 0); } static int __init serverworks_setup (struct pci_dev *pdev) @@ -5131,6 +5020,7 @@ static struct _hp_private { volatile u8 *ioc_regs; volatile u8 *lba_regs; + int lba_cap_offset; u64 *io_pdir; // PDIR for entire IOVA u64 *gatt; // PDIR just for GART (subset of above) u64 gatt_entries; @@ -5183,6 +5073,7 @@ hp->gatt = &hp->io_pdir[HP_ZX1_IOVA_TO_PDIR(hp->gart_base)]; if (hp->gatt[0] != HP_ZX1_SBA_IOMMU_COOKIE) { + /* Normal case when no AGP device in system */ hp->gatt = 0; hp->gatt_entries = 0; printk(KERN_ERR PFX "No reserved IO PDIR entry found; " @@ -5228,12 +5119,13 @@ return 0; } -static int __init hp_zx1_ioc_init(u64 ioc_hpa, u64 lba_hpa) +static int __init hp_zx1_ioc_init(u64 hpa) { struct _hp_private *hp = &hp_private; - hp->ioc_regs = ioremap(ioc_hpa, 1024); - hp->lba_regs = ioremap(lba_hpa, 256); + hp->ioc_regs = ioremap(hpa, 1024); + if (!hp->ioc_regs) + return -ENOMEM; /* * If the IOTLB is currently disabled, we can take it over. @@ -5247,6 +5139,50 @@ return hp_zx1_ioc_shared(); } +static int +hp_zx1_lba_find_capability(volatile u8 *hpa, int cap) +{ + u16 status; + u8 pos, id; + int ttl = 48; + + status = INREG16(hpa, PCI_STATUS); + if (!(status & PCI_STATUS_CAP_LIST)) + return 0; + pos = INREG8(hpa, PCI_CAPABILITY_LIST); + while (ttl-- && pos >= 0x40) { + pos &= ~3; + id = INREG8(hpa, pos + PCI_CAP_LIST_ID); + if (id == 0xff) + break; + if (id == cap) + return pos; + pos = INREG8(hpa, pos + PCI_CAP_LIST_NEXT); + } + return 0; +} + +static int __init hp_zx1_lba_init(u64 hpa) +{ + struct _hp_private *hp = &hp_private; + int cap; + + hp->lba_regs = ioremap(hpa, 256); + if (!hp->lba_regs) + return -ENOMEM; + + hp->lba_cap_offset = hp_zx1_lba_find_capability(hp->lba_regs, PCI_CAP_ID_AGP); + + cap = INREG32(hp->lba_regs, hp->lba_cap_offset) & 0xff; + if (cap != PCI_CAP_ID_AGP) { + printk(KERN_ERR PFX "Invalid capability ID 0x%02x at 0x%x\n", + cap, hp->lba_cap_offset); + return -ENODEV; + } + + return 0; +} + static int hp_zx1_fetch_size(void) { int size; @@ -5262,7 +5198,7 @@ struct _hp_private *hp = &hp_private; agp_bridge.gart_bus_addr = hp->gart_base; - agp_bridge.mode = INREG32(hp->lba_regs, HP_ZX1_AGP_STATUS); + agp_bridge.mode = INREG32(hp->lba_regs, hp->lba_cap_offset + PCI_AGP_STATUS); if (hp->io_pdir_owner) { OUTREG64(hp->ioc_regs, HP_ZX1_PDIR_BASE, @@ -5282,10 +5218,13 @@ { struct _hp_private *hp = &hp_private; - if (hp->io_pdir_owner) - OUTREG64(hp->ioc_regs, HP_ZX1_IBASE, 0); - iounmap((void *) hp->ioc_regs); - iounmap((void *) hp->lba_regs); + if (hp->ioc_regs) { + if (hp->io_pdir_owner) + OUTREG64(hp->ioc_regs, HP_ZX1_IBASE, 0); + iounmap((void *) hp->ioc_regs); + } + if (hp->lba_regs) + iounmap((void *) hp->lba_regs); } static void hp_zx1_tlbflush(agp_memory * mem) @@ -5405,18 +5344,23 @@ struct _hp_private *hp = &hp_private; u32 command; - command = INREG32(hp->lba_regs, HP_ZX1_AGP_STATUS); + command = INREG32(hp->lba_regs, hp->lba_cap_offset + PCI_AGP_STATUS); command = agp_collect_device_status(mode, command); command |= 0x00000100; - OUTREG32(hp->lba_regs, HP_ZX1_AGP_COMMAND, command); + OUTREG32(hp->lba_regs, hp->lba_cap_offset + PCI_AGP_COMMAND, command); agp_device_command(command, 0); } static int __init hp_zx1_setup(u64 ioc_hpa, u64 lba_hpa) { + struct _hp_private *hp = &hp_private; + int error; + + memset(hp, 0, sizeof(*hp)); + agp_bridge.dev_private_data = NULL; agp_bridge.size_type = FIXED_APER_SIZE; agp_bridge.needs_scratch_page = FALSE; @@ -5441,7 +5385,16 @@ fake_bridge_dev.vendor = PCI_VENDOR_ID_HP; fake_bridge_dev.device = PCI_DEVICE_ID_HP_PCIX_LBA; - return hp_zx1_ioc_init(ioc_hpa, lba_hpa); + error = hp_zx1_ioc_init(ioc_hpa); + if (error) + goto fail; + + error = hp_zx1_lba_init(lba_hpa); + +fail: + if (error) + hp_zx1_cleanup(); + return error; } static acpi_status __init hp_zx1_gart_probe(acpi_handle obj, u32 depth, void *context, void **ret) @@ -5455,7 +5408,7 @@ status = acpi_hp_csr_space(obj, &lba_hpa, &length); if (ACPI_FAILURE(status)) - return AE_OK; + return AE_OK; /* keep looking for another bridge */ /* Look for an enclosing IOC scope and find its CSR space */ handle = obj; @@ -5491,7 +5444,7 @@ (char *) context, sba_hpa + HP_ZX1_IOC_OFFSET, lba_hpa); hp_zx1_gart_found = 1; - return AE_CTRL_TERMINATE; + return AE_CTRL_TERMINATE; /* we only support one bridge; quit looking */ } static int __init @@ -6463,7 +6416,6 @@ "IGP9100/M", ati_generic_setup }, #endif /* CONFIG_AGP_ATI */ - { 0, }, /* dummy final entry, always present */ }; @@ -6546,7 +6498,6 @@ return -ENODEV; } - /* Supported Device Scanning routine */ static int __init agp_find_supported_device(void) @@ -6874,7 +6825,7 @@ /* Fill in the mode register */ pci_read_config_dword(agp_bridge.dev, - agp_bridge.capndx + 4, + agp_bridge.capndx + PCI_AGP_STATUS, &agp_bridge.mode); /* probe for known chipsets */ @@ -7092,7 +7043,8 @@ inter_module_register("drm_agp", THIS_MODULE, &drm_agp); - pm_register(PM_PCI_DEV, PM_PCI_ID(agp_bridge.dev), agp_power); + if (agp_bridge.dev) + pm_register(PM_PCI_DEV, PM_PCI_ID(agp_bridge.dev), agp_power); return 0; } diff -Nru a/include/linux/sysctl.h b/include/linux/sysctl.h --- a/include/linux/sysctl.h Fri Mar 12 15:59:51 2004 +++ b/include/linux/sysctl.h Fri Mar 12 15:59:51 2004 @@ -156,6 +156,7 @@ VM_MAPPED_RATIO=20, /* amount of unfreeable pages that triggers swapout */ VM_LAPTOP_MODE=21, /* kernel in laptop flush mode */ VM_BLOCK_DUMP=22, /* dump fs activity to log */ + VM_HUGETLB_PAGES=23, /* int: Number of available Huge Pages */ };